Components › Forms & input › Date & time › Calendar

Calendar

canon

Month grid with navigation and presets, single or range selection.

Calendar PAGE chrome (acrm !3942, AD 27 Sep 2026): month label = SectionTopBarChip opening the jump popover (the page title stays „Kalendář“); year ←→ = IconButton sm; the 12-month grid reuses the day cell `.dp-day` with `.sel` + aria-current — one „selected“ look for date picking, no button variant as state. DELIBERATE EXCEPTION: the nav trio ‹ ● › (previous · today · next) keeps its own look per the owner’s ACRM-91/97/103 (arrows without a hover surface that only darken, „Dnes“ a small grey circle-dot) — real <button>s with aria-label and a focus ring, tokens only; do not convert to IconButton. The day-panel ear (.cal-ear) is a second exception (surface chrome, tokens only).

Used in 7 files · 6 areas · 7× — components/FilterBar, components/callwrapup, components/mail, components/projects, components/tasks, components/timeline

Pattern: ARIA APG "Date picker dialog" grid with roving tabindex.

Keyboard

  • One cell is tabbable (tabindex="0" on the focused day); ←/→ move a day, ↑/↓ a week, Home/End to the first/last day of the week, PageUp/PageDown a month, Shift+PageUp/PageDown a year — the view follows the focused day.
  • Enter or Space picks the day; in range mode the first pick starts, the second closes the range.
  • Esc calls onRequestClose (the host panel closes and returns focus to its field).
  • Presets and nav arrows are native buttons in the tab order before the grid.

ARIA

  • Grid role="grid" with aria-label = month title; cells are <button role="gridcell"> with aria-label (full date), aria-selected on selected days, aria-current="date" on today, disabled outside min/max.
  • Weekday row is aria-hidden (labels are decorative; each cell carries its full date).
  • Month titles .mt have aria-live="polite" so month changes are announced.
  • Nav arrows aria-label="Předchozí měsíc" / "Další měsíc".

Focus

  • Cell ring .dp-day:focus-visible: 0 0 0 1px var(--accent), 0 0 0 4px color-mix(in srgb, var(--accent) 16%, transparent), z-index: 2 above neighbouring band cells; outline: 0.
  • autoFocus moves focus into the grid after mount (used by every panel host).
  • Focus is restored to the real DOM button after each re-render (useLayoutEffect).

Contrast

  • Day --fg on --surface-100: 17.59:1 light, 14.53:1 dark; weekend --fg-secondary: 3.93:1 light (below AA), 6.2:1 dark.
  • Other-month --fg-muted: 2.85:1 light, 3.63:1 dark — decorative context.
  • Today --accent on --surface-100: 4.44:1 light, 3.83:1 dark (13px 600 — below AA in dark).
  • Selected white on --accent: 4.44:1; hover --accent-press: 5.73:1.
  • In-range --accent-ink on --accent-tint: 4.58:1 light, 5.37:1 dark.
  • Disabled --ink-300: 1.97:1 light (exempt).

Known limits

  • Weekend and other-month digits are below AA 4.5:1 in light mode by design (hierarchy by colour).
  • Today in dark mode is 3.83:1 — below AA for 13px text.
  • The range band and the "open end" convention are visual only; no textual equivalent besides aria-selected on the closed end.
  • .dp-day.sel uses a literal #fff, not --fg-on-accent (engine drift, flagged for the token pass).

Source: docs/date-time/calendar.a11y.md · GitLab